package com.openweixin.sheknows.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
/**
 * 通过数据库生成代码的工具类
 * 注意事项：无
 * @author 刘思作
 * @version 1.0.0 2014-04-01
 * @since 1.0.0
 */

public class JavaCreator {
	static String database = "sheknows";
	static List<ClassDesc> tables = new ArrayList<ClassDesc>();

	public static void main(String[] args) throws Exception {
		List<String> tables = new ArrayList<String>();
		tables.add("user");
		tables.add("answer");
		tables.add("expert");
		tables.add("question");
		tables.add("user_login_log");
		tables.add("user_new_answer");
		tables.add("user_new_score");
		String[] classNames = tables.toArray(new String[tables.size()]);
		String path = "E:/GEN/sheknows/";
		String pack = "com.openweixin.sheknows";
		genService(classNames, path, pack);
		genDao(classNames, path, pack);
		genController(classNames, path, pack);
		generate(classNames, path, pack);
	}

	public static void generate(String[] classNames, String path, String pack)
			throws Exception {

		Class.forName("com.mysql.jdbc.Driver");
		Connection con = DriverManager.getConnection(
				"jdbc:mysql://localhost:3306/information_schema", "root",
				"root");

		for (String tableName : classNames) {
			PreparedStatement ps = con
					.prepareStatement("SELECT TABLE_NAME,TABLE_COMMENT FROM TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME=?");
			ps.setString(1, database);
			ps.setString(2, tableName);
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				tables.add(new ClassDesc(rs.getString(1), rs.getString(2)));
			}
			rs.close();
			ps.close();
		}

		for (ClassDesc cla : tables) {
			List<String[]> beanPropTyps = new ArrayList<String[]>();
			cla.setProps(beanPropTyps);
			String tableName = cla.getTableName();
			cla.setClassName(CoderGenerate.tableToClass(tableName, true));
			PreparedStatement ps = con
					.prepareStatement("SELECT COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT "
							+ "FROM COLUMNS "
							+ "WHERE TABLE_SCHEMA = ? AND TABLE_NAME=?");
			ps.setString(1, database);
			ps.setString(2, tableName);

			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				String field = CoderGenerate.tableToClass(rs.getString(1));
				String type = rs.getString(2);
				String comment = rs.getString(3);
				String columnName = rs.getString(1);
				beanPropTyps.add(new String[] { field, type, comment,
						columnName });
			}
			rs.close();
			ps.close();
		}
		genBean(tables, path, pack);

	}

	public static class ClassDesc {
		private String className;
		private String comment;
		private String tableName;
		private List<String[]> props;

		public String getClassName() {
			return className;
		}

		public void setClassName(String className) {
			this.className = className;
		}

		public String getComment() {
			return comment;
		}

		public void setComment(String comment) {
			this.comment = comment;
		}

		public String getTableName() {
			return tableName;
		}

		public void setTableName(String tableName) {
			this.tableName = tableName;
		}

		public List<String[]> getProps() {
			return props;
		}

		public void setProps(List<String[]> props) {
			this.props = props;
		}

		private ClassDesc(String tableName, String comment) {
			super();
			this.tableName = tableName;
			this.comment = comment;
		}

	}

	private static void genBean(List<ClassDesc> descList, String path,
			String pack) {
		String subPath = pack.replace('.', '\\');
		File domain = new File(path + subPath + "/domain/");
		if (!domain.exists()) {
			domain.mkdirs();
		}

		for (ClassDesc classDesc : descList) {
			String clsName = classDesc.getClassName();
			String tabName = classDesc.getTableName();
			String comment = classDesc.getComment();
			List<String[]> prop = classDesc.getProps();
			StringBuffer sb = new StringBuffer();

			sb.append("package " + pack + ".domain;\n");
			sb.append("\n");
			sb.append("import javax.persistence.Column;\n");
			sb.append("import javax.persistence.Entity;\n");
			sb.append("import javax.persistence.Table;\n");
			boolean isHaveDecimal = false;
			for (String[] ftc : prop) {
				if (getType(ftc[1]).equals("BigDecimal")) {
					isHaveDecimal = true;
					break;
				}
			}
			boolean isHaveDate = false;

			for (String[] ftc : prop) {
				if (getType(ftc[1]).equals("Date")) {
					isHaveDate = true;
					break;
				}
			}
			if (isHaveDecimal)
				sb.append("import java.math.BigDecimal;\n");
			if (isHaveDate)
				sb.append("import java.util.Date;\n");

			sb.append("\n");
			sb.append("/**\n");
			sb.append(" * 实体类-" + comment + "\n");
			sb.append(" * @注意事项  无\n");
			sb.append(" * @author 刘思作\n");
			sb.append(" * @version 1.0.0 2014-04-02\n");
			sb.append(" * @since 1.0.0\n");
			sb.append(" */\n");
			sb.append("\n");
			sb.append("@Entity\n");
			sb.append("@Table(name = \"" + tabName + "\")\n");
			sb.append("public class " + clsName + "{\n");
			sb.append("\n");
			sb.append("\n");

			for (String[] ftc : prop) {
				if (ftc[0].equals("id") || ftc[0].equals("createTime")
						|| ftc[0].equals("updateTime")) {
					continue;
				}
				sb.append("	private " + getType(ftc[1]) + " " + ftc[0] + ";//"
						+ ftc[2] + "\n");
			}
			sb.append("\n");
			for (String[] ftcc : prop) {
				if (ftcc[0].equals("id") || ftcc[0].equals("createTime")
						|| ftcc[0].equals("updateTime")) {
					continue;
				}
				sb.append("	@Column(name=\"" + ftcc[3] + "\") \n");
				if (getType(ftcc[1]).equals("Boolean")) {
					sb.append("	public " + getType(ftcc[1]) + " is"
							+ upper(ftcc[0]) + "(){\n");
				} else {
					sb.append("	public " + getType(ftcc[1]) + " get"
							+ upper(ftcc[0]) + "(){\n");
				}
				sb.append("		return this." + ftcc[0] + ";\n");
				sb.append("	}\n");
				sb.append("\n");
				sb.append("	public void set" + upper(ftcc[0]) + "("
						+ getType(ftcc[1]) + " " + ftcc[0] + "){\n");
				sb.append("		this." + ftcc[0] + "=" + ftcc[0] + ";\n");
				sb.append("	}\n");
				sb.append("\n");
			}
			sb.append("}");

			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(new File(domain, clsName + ".java"));
				IOUtils.write(sb.toString(), fos);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static String upper(String name) {
		return name.substring(0, 1).toUpperCase() + name.substring(1);
	}

	public static String getType(String type) {
		System.out.println(type);
		if (type.startsWith("int")) {
			return "Integer";
		} else if (type.startsWith("tinyint")) {
			return "Boolean";
		} else if (type.startsWith("decimal")) {
			return "BigDecimal";
		} else if (type.equals("float")) {
			return "Float";
		} else if (type.startsWith("char") || type.startsWith("var")|| type.equals("text")) {
			return "String";
		} else if (type.startsWith("date")) {
			return "Date";
		} else if(type.equals("timestamp")){
			return "java.sql.Timestamp";
		} else if(type.startsWith("small")) {
			return "Short";
		} 
		return "";
	}

	private static void genController(String[] classNames, String path,
			String pack) {
		String subPath = pack.replace('.', '\\');
		File control = new File(path + subPath + "/controller/");
		if (!control.exists()) {
			control.mkdirs();
		}
		for (String clsName : classNames) {
			clsName = CoderGenerate.tableToClass(clsName, true);
			StringBuffer sb = new StringBuffer();
			sb.append("package " + pack + ".controller;\n");
			sb.append("import org.springframework.beans.factory.annotation.Autowired;\n");
			sb.append("import org.springframework.stereotype.Controller;\n");
			sb.append("import org.springframework.web.bind.annotation.RequestMapping;\n");
			sb.append("import org.springframework.web.bind.annotation.ResponseBody;\n");
			sb.append("import org.springframework.web.bind.annotation.RequestBody;\n");
			sb.append("import com.openweixin.sheknows.common.Pager;\n");
			sb.append("import " + pack + ".service." + clsName + "Service;\n");
			sb.append("import " + pack + ".domain." + clsName + ";\n");
			sb.append("@Controller\n");
			sb.append("@RequestMapping(\"/" + StringUtils.uncapitalize(clsName)
					+ "\")\n");

			sb.append("public class " + clsName
					+ "Controller extends BaseController{\n");
			sb.append("\n");
			sb.append("	@Autowired\n");
			sb.append("	private " + clsName + "Service service;\n");
			sb.append("\n");
			sb.append("	@RequestMapping\n");
			sb.append("	public String toMain(){\n");
			sb.append("		return \"" + clsName + "\";\n");
			sb.append("	}\n");
			sb.append("\n");

			sb.append("	@RequestMapping(\"/list\")\n");
			sb.append("	@ResponseBody \n");
			sb.append("	public Pager<" + clsName + "> list(Pager<" + clsName
					+ "> pager){\n");
			sb.append("		pager = service.findByPager(pager);\n");
			sb.append("		return pager;\n");
			sb.append("	}\n");
			sb.append("\n");

			sb.append("	@RequestMapping(\"/add\")\n");
			sb.append("	@ResponseBody \n");
			sb.append("	public String add(@RequestBody " + clsName
					+ " bean){\n");
			sb.append("		service.save(bean);\n");
			sb.append("		return SUCCESS; \n");
			sb.append("	}\n");
			sb.append("\n");

			sb.append("	@RequestMapping(\"/update\")\n");
			sb.append("	@ResponseBody \n");
			sb.append("	public String update(@RequestBody " + clsName
					+ " bean){\n");
			sb.append("		service.update(bean);\n");
			sb.append("		return SUCCESS; \n");
			sb.append("	}\n");
			sb.append("\n");

			sb.append("	@RequestMapping(\"/delete\")\n");
			sb.append("	@ResponseBody \n");
			sb.append("	public String delete(Integer[] ids){\n");
			sb.append("		service.delete(ids);\n");
			sb.append("		return SUCCESS; \n");
			sb.append("	}\n");
			sb.append("\n");

			sb.append("}\n");

			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(new File(control, clsName
						+ "Controller.java"));
				IOUtils.write(sb.toString(), fos);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	private static void genService(String[] classNames, String path, String pack) {
		String subPath = pack.replace('.', '\\');
		File serviceDir = new File(path + subPath + "/service/");
		if (!serviceDir.exists()) {
			serviceDir.mkdirs();
		}
		File implDir = new File(path + subPath + "/service/impl/");
		if (!implDir.exists()) {
			implDir.mkdirs();
		}

		for (String clsName : classNames) {
			clsName = CoderGenerate.tableToClass(clsName, true);
			StringBuffer sb = new StringBuffer();
			sb.append("package " + pack + ".service.impl;\n");
			sb.append("import javax.annotation.Resource;\n");
			sb.append("import org.springframework.stereotype.Service;\n");
			sb.append("import " + pack + ".service." + clsName + "Service;\n");
			sb.append("import " + pack + ".dao." + clsName + "Dao;\n");
			sb.append("import " + pack + ".domain." + clsName + ";\n");
			sb.append("@Service\n");
			sb.append("public class " + clsName
					+ "ServiceImpl extends BaseServiceImpl<" + clsName
					+ ", Integer> implements " + clsName + "Service { \n");
			sb.append("	@Resource\n");
			sb.append("	public void setBaseDao(" + clsName + "Dao dao) {\n");
			sb.append("		super.setBaseDao(dao);\n");
			sb.append("	}\n");
			sb.append("}\n");
			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(new File(implDir, clsName
						+ "ServiceImpl.java"));
				IOUtils.write(sb.toString(), fos);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			StringBuffer newsb = new StringBuffer();
			newsb.append("package " + pack + ".service;\n");
			newsb.append("import " + pack + ".domain." + clsName + ";\n");
			newsb.append("public interface " + clsName
					+ "Service extends BaseService<" + clsName
					+ ", Integer> {\n");
			newsb.append("}\n");

			FileOutputStream fos2 = null;
			try {
				fos2 = new FileOutputStream(new File(serviceDir, clsName
						+ "Service.java"));
				IOUtils.write(newsb.toString(), fos2);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos2.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void genDao(String[] classNames, String path, String pack) {
		String subPath = pack.replace('.', '\\');
		File daoDir = new File(path + subPath + "/dao/");
		if (!daoDir.exists()) {
			daoDir.mkdirs();
		}
		File implDir = new File(path + subPath + "/dao/impl/");
		if (!implDir.exists()) {
			implDir.mkdirs();
		}

		for (String clsName : classNames) {
			clsName = CoderGenerate.tableToClass(clsName, true);
			StringBuffer sb = new StringBuffer();
			sb.append("package " + pack + ".dao.impl;\n");
			sb.append("import org.springframework.stereotype.Repository;\n");
			sb.append("import " + pack + ".dao." + clsName + "Dao;\n");
			sb.append("import " + pack + ".domain." + clsName + ";\n");
			sb.append("@Repository\n");
			sb.append("public class " + clsName
					+ "DaoImpl extends BaseDaoImpl<" + clsName
					+ ", Integer> implements " + clsName + "Dao { \n");
			sb.append("}\n");
			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(new File(implDir, clsName
						+ "DaoImpl.java"));
				IOUtils.write(sb.toString(), fos);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			StringBuffer newsb = new StringBuffer();
			newsb.append("package " + pack + ".dao;\n");
			newsb.append("import " + pack + ".domain." + clsName + ";\n");
			newsb.append("public interface " + clsName + "Dao extends BaseDao<"
					+ clsName + ", Integer> {\n");
			newsb.append("}\n");

			FileOutputStream fos2 = null;
			try {
				fos2 = new FileOutputStream(new File(daoDir, clsName
						+ "Dao.java"));
				IOUtils.write(newsb.toString(), fos2);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos2.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
